﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using netDxf.Tables;
using netDxf;
using TAMDWGSDB121;
using netDxf.Entities;
using netDxf.Blocks;
using System.Runtime.InteropServices;
using System.Drawing.Text;
using System.Drawing;
using SDBConverter.Models;
using netDxf.Header;

namespace DxfViewer
{
    /// <summary>
    /// This class is responsible for processing SDB files and converting them to DXF format.   
    /// </summary>
    public class SDB2DxfProcessor
    {
        #region properties 
        private const string LAYER_TEXT = "TEXT";
        private const string LAYER_LINE = "LINE";
        private const string LAYER_DASH = "DASH";
        private AciColor lineColor= AciColor.Default;
        private AciColor dashColor = AciColor.Default;
        private AciColor textColor = AciColor.Default;
        Dictionary<string, List<string>> drawnTextCache = new Dictionary<string, List<string>>();

        private int leftXBorder = int.MinValue;
        #endregion
        public SDB2DxfProcessor(int lineColorV, int dashColorV, int textColorV) {
            lineColor= AciColor.FromTrueColor(lineColorV);
            dashColor = AciColor.FromTrueColor(dashColorV);
            textColor = AciColor.FromTrueColor(textColorV);

            //// 初始化颜色列表  
            //for (short i = 1; i <= 9; i++) {
            //    lineColorDic.Add(i, new AciColor(i));
            //}
            //lineColorDic[5] = AciColor.FromTrueColor(0x551173);
            //lineColorDic[6] = AciColor.FromTrueColor(0x04e5e6);
            //lineColorDic[1] = AciColor.FromTrueColor(0xd4d6d7);
            //lineColorDic.Add(24, AciColor.FromTrueColor(0x910607));

            //txtColorDic.Add(393216, AciColor.Cyan);
            //txtColorDic.Add(65536, new AciColor(221, 222, 223));
            //txtColorDic.Add(2293760, new AciColor(255, 255, 255));
            //txtColorDic.Add(1572864, AciColor.FromTrueColor(0xa00102));
        }

        public DxfDocument ProcessFile(string filePath) {
            drawnTextCache = new Dictionary<string, List<string>>();
            List<CViewPatch> sdbData = SDBLOAD.loadSDBFile(filePath);
            DxfDocument dxfDocument = new DxfDocument(DxfVersion.AutoCad2013);

            // Manually define a DashDotX2-like pattern
            LineType dashDotX2 = new LineType("DashDotX2")
            {
                Description = "Dash dot scaled 2x",
                Segments = new List<double> { 8.0, -2.0, 0.0, -2.0 }// Dash， Gap, Dot, Gap
            };
            // Optionally add to the document (not necessary if used directly in the entity)
            dxfDocument.LineTypes.Add(dashDotX2);
            Dictionary<string, Layer> dxfLayers = new Dictionary<string, Layer>
            {
                { LAYER_LINE, new Layer("划线层"){Color = lineColor} },
                { LAYER_DASH, new Layer("不印字划线层"){Color = dashColor} },
                { LAYER_TEXT, new Layer("印字层"){Color = textColor} }
            };
            dxfDocument.Layers.Add(dxfLayers[LAYER_LINE]);
            dxfDocument.Layers.Add(dxfLayers[LAYER_DASH]);
            dxfDocument.Layers.Add(dxfLayers[LAYER_TEXT]);

            // 获取所有三角框的文本ID
            List<int> triangleTextIds = GetTriangleTextIds(sdbData);
            // 获取左下角信息框位置
            leftXBorder = getXleftBorder(sdbData);
            // 层级筛选
            int max_layer_count = 0;
            foreach (var sdb in sdbData) {
                int countView = 0;
                foreach (var view in sdb.lst_view_view) {
                    string layerName = GetLayerName(view);
                    if (!layerName.StartsWith("PLOT") && countView > max_layer_count) {
                        continue;
                    }

                    //ProcessSubPictures(view.lst_pict_view, dxfLayers[LAYER_TEXT], dxfDocument);// aodc:添加图片处理
                    ProcessContours(view.lst_contours, dxfLayers, dxfDocument);
                    ProcessTexts(view.lst_text, dxfLayers[LAYER_TEXT], dxfDocument, triangleTextIds);

                    foreach (var subview in view.lst_view_subview) {
                        ProcessSubview(subview, dxfLayers, dxfDocument, triangleTextIds);
                    }

                    countView++;
                }
            }

            return dxfDocument;
        }

        private List<int> GetTriangleTextIds(List<CViewPatch> sdbData)
        {
            try
            {
                List<AvevaGeoPoints> geoPoints = new List<AvevaGeoPoints>();
                Dictionary<int, AvevaGeoPoints> pointDict = new Dictionary<int, AvevaGeoPoints>();
                Dictionary<int, _SDB_TEXT_> textDic = new Dictionary<int, _SDB_TEXT_>();
                foreach (var sdb in sdbData)
                {
                    foreach (var geo in sdb.lst_geo_nodes)
                    {
                        if (!pointDict.ContainsKey(geo.GetID()))
                        {
                            geoPoints.Add(new AvevaGeoPoints(geo.GetID(), geo.GetNextID(), geo.GetUppID()));
                            pointDict.Add(geo.GetID(), new AvevaGeoPoints(geo.GetID(), geo.GetNextID(), geo.GetUppID()));
                            if (!pointDict.ContainsKey(geo.GetUppID()))
                            {
                                geoPoints.Add(new AvevaGeoPoints(geo.GetUppID(), geo.GetID(), 0));
                                pointDict.Add(geo.GetUppID(), new AvevaGeoPoints(geo.GetUppID(), geo.GetID(), 0));
                            }
                        }
                    }

                    foreach (var txt in sdb.lst_text)
                    {
                        if (!textDic.ContainsKey(txt.node.GetID()))
                        {
                            textDic.Add(txt.node.GetID(), txt);
                        }
                    }
                }

                List<List<int>> circules = FindAllCircles(geoPoints);
                List<List<int>> allNumberCircules = new List<List<int>>();
                foreach (var circule in circules)
                {
                    bool allNumbers = true;
                    StringBuilder sb = new StringBuilder();
                    foreach (var pointId in circule)
                    {
                        if (textDic.ContainsKey(pointId))
                        {
                            if (!string.IsNullOrEmpty(textDic[pointId].TXT) && !textDic[pointId].TXT.All(char.IsDigit))
                            {
                                allNumbers = false;
                                break;
                            }
                            else if (textDic[pointId].itmp_4 == 0)
                            {
                                allNumbers = false;
                                break;
                            }

                            sb.Append(textDic[pointId].TXT);
                        }
                    }
                    if (allNumbers && !string.IsNullOrEmpty(sb.ToString()))
                    {
                        allNumberCircules.Add(circule);
                    }
                }

                List<int> triangleTextIds = new List<int>();
                foreach (var circule in allNumberCircules)
                {
                    foreach (var pointId in circule)
                    {
                        if (textDic.ContainsKey(pointId))
                        {
                            triangleTextIds.Add(pointId);
                        }
                    }
                }

                return triangleTextIds;
            }
            catch (Exception ex)
            {
                return new List<int>();
            }
        }
        public static List<List<int>> FindAllCircles(List<AvevaGeoPoints> points)
        {
            var circles = new List<List<int>>();
            var visited = new HashSet<int>();
            Dictionary<int, AvevaGeoPoints> pointDict = new Dictionary<int, AvevaGeoPoints>();
            foreach (var p in points)
            {
                if (!pointDict.ContainsKey(p.ID))
                {
                    pointDict.Add(p.ID, p);
                }
            }            

            foreach (var point in points)
            {
                if (!visited.Contains(point.ID))
                {
                    var currentPath = new List<int>();
                    var currentId = point.ID;

                    while (true)
                    {
                        // If we've already visited this point or it doesn't exist
                        if (visited.Contains(currentId) || !pointDict.ContainsKey(currentId))
                        {
                            break;
                        }

                        visited.Add(currentId);
                        currentPath.Add(currentId);

                        // Move to next point
                        currentId = pointDict[currentId].Next;

                        // Check if we've completed a circle
                        if (currentPath.Contains(currentId))
                        {
                            // Extract just the circular portion
                            var circleStartIndex = currentPath.IndexOf(currentId);
                            var circle = currentPath.Skip(circleStartIndex).ToList();
                            circles.Add(circle);
                            break;
                        }

                        // Prevent infinite loops in case of malformed data
                        if (currentPath.Count > points.Count)
                        {
                            break;
                        }
                    }
                }
            }

            return circles;
        }

        private void ProcessSubview(CViewSubview subview, Dictionary<string, Layer> parentLayers, DxfDocument dxfDoc, List<int> triangleTextIds)
        {
            ProcessSubPictures(subview.lst_pict_subview, parentLayers[LAYER_LINE], dxfDoc);
            //ProcessContours(subview.lst_contours, parentLayer, dxfDoc);
            //ProcessTexts(subview.lst_text, parentLayer, dxfDoc);
            foreach (var component in subview.lst_view_component)
            {
                ProcessComponent(component, parentLayers, dxfDoc, triangleTextIds);
            }
        }

        private void ProcessComponent(CViewComponent component, Dictionary<string, Layer> parentLayers, DxfDocument dxfDoc, List<int> triangleTextIds)
        {
            ProcessContours(component.lst_contours, parentLayers, dxfDoc);
            ProcessTexts(component.lst_text, parentLayers[LAYER_TEXT], dxfDoc, triangleTextIds);
        }

        private void ProcessContours(List<_SDB_CONTOUR_> contours, Dictionary<string, Layer> layers, DxfDocument dxfDoc)
        {
            foreach (var contour in contours)
            {
                if (contour.num_pt < 1) continue;
                
                Vector2 currentPoint = new Vector2(contour.pt_s.x, contour.pt_s.y);
                //AciColor color = defaultColor;
                //if (lineColorDic.ContainsKey(contour.stmp_6))
                //{
                //    color = lineColorDic[contour.stmp_6];
                //}

                Layer layer = layers[LAYER_LINE];
                if (contour.stmp_6 == 5)
                {
                    layer = layers[LAYER_DASH];
                }

                foreach (var section in contour.pt_n)
                {
                    Vector2 nextPoint = new Vector2(section.pt_e.x, section.pt_e.y);
                    if (currentPoint.X < leftXBorder || nextPoint.X < leftXBorder) {
                        continue;
                    }
                    if (Math.Abs(section.amp) < 0.1)
                    {
                        if (contour.stmp_6 == 5)
                        {
                            // Manually define a DashDotX2-like pattern
                            LineType dashDotX2 = new LineType("DashDotX2")
                            {
                                Description = "Dash dot scaled 2x",
                                Segments = new List<double> { 8.0, -2.0, 0.0, -2.0 }// Dash, Gap, Dot, Gap
                            };
                            //dxfDoc.AddEntity(new Line(currentPoint, nextPoint) { Layer = layer, Color = color, LineType = dashDotX2 });
                            dxfDoc.AddEntity(new Line(currentPoint, nextPoint) { Layer = layer, Color = AciColor.ByLayer, LineType = dashDotX2 });
                        }
                        else
                        {
                            //dxfDoc.AddEntity(new Line(currentPoint, nextPoint) { Layer = layer, Color = color });
                            dxfDoc.AddEntity(new Line(currentPoint, nextPoint) { Layer = layer, Color = AciColor.ByLayer });
                        }
                    }
                    else
                    {
                        // 输入已知数据
                        double x1 = currentPoint.X;
                        double y1 = currentPoint.Y;
                        double x2 = nextPoint.X;
                        double y2 = nextPoint.Y;
                        double z = section.amp; // 圆心到弦的垂直距离

                        // 1. 弦中点
                        double mx = (x1 + x2) / 2.0;
                        double my = (y1 + y2) / 2.0;

                        // 2. 弦方向向量
                        double dx = x2 - x1;
                        double dy = y2 - y1;
                        double L = Math.Sqrt(dx * dx + dy * dy); // 弦长

                        if (L == 0)
                        {
                            Console.WriteLine("弦长度为 0，无法计算圆");
                            return;
                        }

                        // 3. 计算 d
                        double halfL = L / 2.0;
                        double numerator = (halfL * halfL) - (z * z);
                        double denominator = 2.0 * z;

                        double d = numerator / denominator;

                        // 4. 半径 r
                        double r = z + d;

                        // 5. 弦的垂直单位向量 (逆时针旋转 90°)
                        double nx = -dy / L;
                        double ny = dx / L;

                        // 6. 圆心坐标
                        double cx = mx + d * nx;
                        double cy = my + d * ny;

                        // 7. 计算两个点相对于圆心的角度
                        double startAngle = Math.Atan2(y1 - cy, x1 - cx) * (180.0 / Math.PI);
                        double endAngle = Math.Atan2(y2 - cy, x2 - cx) * (180.0 / Math.PI);
                        if (startAngle < 0)
                        {
                            startAngle = Math.Abs(startAngle) < 0.001 ? 0.00001 : startAngle + 360;
                        }

                        if (endAngle < 0)
                        {
                            endAngle = Math.Abs(endAngle) < 0.001 ? 0.00001 : endAngle + 360;
                        }
                        if (Math.Abs(section.amp) > 0.001 && section.amp < 0)
                        {
                            double tmp = startAngle;
                            startAngle = endAngle;
                            endAngle = tmp;
                        }

                        // 7. Create Arc and save
                        if (startAngle > endAngle)
                        {
                            //var arcAboveZero = createArcModel(cx, cy, Math.Abs(r), startAngle, 360, layer, color);
                            var arcAboveZero = createArcModel(cx, cy, Math.Abs(r), startAngle, 360, layer, AciColor.ByLayer);
                            dxfDoc.AddEntity(arcAboveZero);

                            //var arcBelowZero = createArcModel(cx, cy, Math.Abs(r), 0, endAngle, layer, color);
                            var arcBelowZero = createArcModel(cx, cy, Math.Abs(r), 0, endAngle, layer, AciColor.ByLayer);
                            dxfDoc.AddEntity(arcBelowZero);
                        }
                        else
                        {
                            //var arc = createArcModel(cx, cy, Math.Abs(r), startAngle, endAngle, layer, color);
                            var arc = createArcModel(cx, cy, Math.Abs(r), startAngle, endAngle, layer, AciColor.ByLayer);
                            dxfDoc.AddEntity(arc);
                        }
                    }

                    currentPoint = nextPoint;                    
                }
            }
        }

        private  Arc createArcModel(double cx, double cy, double r, double startAngle, double endAngle, Layer layer, AciColor color)
        {
            return new Arc(new Vector2(cx, cy), Math.Abs(r), startAngle, endAngle)
            {
                Layer = layer,
                Color = color
            };
        }

        private void ProcessTexts(List<_SDB_TEXT_> texts, Layer layer, DxfDocument dxfDoc, List<int> triangleTextIds) {
            foreach (var text in texts) {
                if (text.pt_pos.x < leftXBorder) {
                    continue;
                }
                string content = Encoding.UTF8.GetString(text.txt);
                content = content.StartsWith("%B") ? content.Substring(2) : content;
                //AciColor color = defaultColor;
                //if (txtColorDic.ContainsKey(text.itmp_4))
                //{
                //    color = txtColorDic[text.itmp_4];
                //}

                string key = text.pt_pos.x.ToString("0.0") + "_" + text.pt_pos.y.ToString("0.0");
                if (triangleTextIds.Contains(text.node.GetID())) {
                    if (drawnTextCache.ContainsKey(key) && drawnTextCache[key].Contains(text.TXT)) {
                        continue;
                    } else {
                        drawnTextCache.Add(key, new List<string> { text.TXT });
                    }
                    double height = Math.Abs(Math.Round(text.height) - text.height) < 0.001 ? Math.Round(text.height) : Math.Ceiling(text.height);
                    double sideLen = 3.32645 * height + 0.0193;
                    //DrawTextTriangle(sideLen, text.rotate, text.TXT, text.height, text.pt_pos.x, text.pt_pos.y, color, layer, dxfDoc);
                    DrawTextTriangle(sideLen, text.rotate, text.TXT, text.height, text.pt_pos.x, text.pt_pos.y, AciColor.ByLayer, layer, dxfDoc);

                } else if (content.StartsWith("#<")) {
                    string textContent = content.Substring(2); // 去掉前缀
                    if (drawnTextCache.ContainsKey(key) && drawnTextCache[key].Contains(textContent)) {
                        continue;
                    } else {
                        drawnTextCache.Add(key, new List<string> { textContent });
                    }
                    // 1. 添加文本
                    //var textStyle = new TextStyle("Courier New"); // 使用等宽字体 Cascadia Code
                    var textStyle = new TextStyle("Cascadia Code");
                    var textEntity = new Text(textContent, new Vector2(text.pt_pos.x, text.pt_pos.y), text.height)
                    {
                        Layer = layer,
                        Style = textStyle,
                        Color = AciColor.ByLayer, //Color = color,
                        Rotation = text.rotate,
                        Alignment = TextAlignment.BaselineLeft // 根据实际需求调整对齐方式
                    };
                    dxfDoc.AddEntity(textEntity);

                    // 2. 添加下划线（估算文本宽度）
                    double widthEstimate = GetTextWidth(textContent, "Arial", text.height);
                    // 2. 计算下划线位置
                    double distanceToBaseline = 0.8; // 下划线到基线的距离
                    Vector2 underlineStart = new Vector2(text.pt_pos.x, text.pt_pos.y - distanceToBaseline);
                    Vector2 underlineEnd = new Vector2(text.pt_pos.x + widthEstimate, text.pt_pos.y - distanceToBaseline);
                    double radians = text.rotate * Math.PI / 180.0;
                    // 3. 旋转下划线（若文字有角度）
                    if (radians != 0) {
                        var position = new Vector2(text.pt_pos.x, text.pt_pos.y);
                        underlineStart = RotatePoint(underlineStart, position, radians);
                        underlineEnd = RotatePoint(underlineEnd, position, radians);
                    }

                    // 4. 创建下划线
                    Line underline = new Line(
                        new Vector3(underlineStart.X, underlineStart.Y, 0),
                        new Vector3(underlineEnd.X, underlineEnd.Y, 0)
                    )
                    {
                        Layer = layer,
                        Color = AciColor.ByLayer   //Color = color 
                    };
                    dxfDoc.AddEntity(underline);
                } else {
                    //var textStyle = new TextStyle("Courier New"); // 使用等宽字体
                    if (drawnTextCache.ContainsKey(key) && drawnTextCache[key].Contains(content)) {
                        continue;
                    } else {
                        drawnTextCache.Add(key, new List<string> { content });
                    }
                    var textStyle = new TextStyle("Cascadia Code");
                    var textEntity = new Text(
                        content,
                        new Vector2(text.pt_pos.x, text.pt_pos.y),
                        text.height)
                    {
                        Layer = layer,
                        Style = textStyle,
                        Color = AciColor.ByLayer, // Color = color,
                        Rotation = text.rotate,
                        Alignment = TextAlignment.BaselineLeft // 根据实际需求调整对齐方式
                    };
                    dxfDoc.AddEntity(textEntity);
                }
            }
        }

        private double GetTextWidth(string text, string fontName, double height)
        {
            using (var bmp = new Bitmap(1, 1))
            using (var g = Graphics.FromImage(bmp))
            {
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
                var font = new Font(fontName, (float)height);
                double len = g.MeasureString(text, font).Width;
                int dotCount = text.Count(c => c == '.');
                return len + dotCount * 1.5;
            }
        }

        private void DrawTextTriangle(double sideLength, double rotationDeg, string content, float text_height, float pos_x, float pos_y, AciColor text_color, Layer layer, DxfDocument dxfDoc)
        {
            // === Input from user (text properties) ===
            //double sideLength = 13.3224;//?? 是否是固定的？
            var textPos = new Vector3(pos_x, pos_y, 0);

            // === Geometry setup ===
            double rotationRad = rotationDeg * Math.PI / 180.0;

            // Compute base line start and end (p1, p2)
            Vector2 p1 = new Vector2(
                textPos.X - (sideLength / 2.0) * Math.Cos(rotationRad),
                textPos.Y - (sideLength / 2.0) * Math.Sin(rotationRad)
            );

            Vector2 p2 = new Vector2(
                textPos.X + (sideLength / 2.0) * Math.Cos(rotationRad),
                textPos.Y + (sideLength / 2.0) * Math.Sin(rotationRad)
            );

            // Height of equilateral triangle
            double height = Math.Sqrt(3) / 2 * sideLength;

            double triangleAngle = rotationRad + Math.PI / 2.0; // perpendicular direction opposite to text

            Vector2 p3 = new Vector2(
                textPos.X + height * Math.Cos(triangleAngle),
                textPos.Y + height * Math.Sin(triangleAngle)
            );

            // Move text slightly above base line (optional: 10% of height)
            double textOffset = height * 0.1;
            Vector3 adjustedTextPos = new Vector3(
                textPos.X + textOffset * Math.Cos(rotationRad + Math.PI / 2.0),
                textPos.Y + textOffset * Math.Sin(rotationRad + Math.PI / 2.0),
                0
            );

            // === Create triangle lines ===
            dxfDoc.AddEntity(new Line(p1, p2) { Layer = layer, Color = AciColor.FromTrueColor(0x05dcdd) });
            dxfDoc.AddEntity(new Line(p2, p3) { Layer = layer, Color = AciColor.FromTrueColor(0x05dcdd) });
            dxfDoc.AddEntity(new Line(p3, p1) { Layer = layer, Color = AciColor.FromTrueColor(0x05dcdd) });

            // === Create the text centered on base ===
            var text = new MText
            {
                Value = content,
                Position = adjustedTextPos,
                Rotation = rotationDeg,
                Color = text_color,
                Height = text_height,
                AttachmentPoint = MTextAttachmentPoint.BottomCenter,
                Layer = layer
            };
            dxfDoc.AddEntity(text);
        }

        private void ProcessSubPictures(List<_SDB_SUBPICTURE_> subpictures, Layer layer, DxfDocument dxfDoc)
        {
            foreach (var subpic in subpictures)
            {
                string blockName = "UnnamedBlock_" + Guid.NewGuid().ToString("N").Substring(0, 8);
                if (subpic.name != null && subpic.name.Length > 0)
                {
                    try { blockName = Encoding.UTF8.GetString(subpic.name).Trim(); }
                    catch { /* 处理异常 */ }
                }
                var block = new Block(blockName);
                block.Entities.Add(new Circle(new Vector2(0, 0), 0.1f));
                dxfDoc.Blocks.Add(block);
                dxfDoc.AddEntity(new Insert(block, new Vector2(0, 0)) { Layer = layer });
            }
        }

        private string GetLayerName(CViewView view)
        {
            return view.lst_pict_view.Count > 0 ?
                Encoding.UTF8.GetString(view.lst_pict_view[0].name) :
                "DefaultLayer";
        }

        private Vector2 RotatePoint(Vector2 point, Vector2 center, double radians)
        {
            double cosTheta = Math.Cos(radians);
            double sinTheta = Math.Sin(radians);
            double translatedX = point.X - center.X;
            double translatedY = point.Y - center.Y;
            double rotatedX = translatedX * cosTheta - translatedY * sinTheta;
            double rotatedY = translatedX * sinTheta + translatedY * cosTheta;
            return new Vector2(rotatedX + center.X, rotatedY + center.Y);
        }

        #region 获取左下角内容位置并清理
        class HorizontalLineCoordinate {
            public int FromX;
            public int FromY;
            public int ToX;
        }

        private int getXleftBorder(List<CViewPatch> sdbData) {
            List<HorizontalLineCoordinate> horiLineCache = new List<HorizontalLineCoordinate>();
            foreach (var sdb in sdbData) {
                int countView = 0;
                foreach (var view in sdb.lst_view_view) {
                    string layerName = GetLayerName(view);
                    if (!layerName.StartsWith("PLOT") && countView > 0) {
                        continue;
                    }
                    horiLineCache.AddRange(getHorizontalLines(view.lst_contours));
                    foreach (var subview in view.lst_view_subview) {
                        foreach (var component in subview.lst_view_component) {
                            horiLineCache.AddRange(getHorizontalLines(component.lst_contours));
                        }
                    }
                    countView++;
                }
            }
            int minX = int.MaxValue;
            int minY = int.MaxValue;
            int toX = int.MinValue;
            foreach (var l in horiLineCache) {
                if (l.FromX <= minX) {
                    if (l.FromX == minX) {
                        if (l.FromY < minY) {
                            minX = l.FromX;
                            minY = l.FromY;
                            toX = l.ToX;
                            if (l.ToX < minX) {
                                minX = l.ToX;
                                toX = l.FromX;
                            }
                        }
                    } else {
                        minX = l.FromX;
                        minY = l.FromY;
                        toX = l.ToX;
                        if (l.ToX < minX) {
                            minX = l.ToX;
                            toX = l.FromX;
                        }
                    }
                }
            }
            //Console.WriteLine($"min_x:{minX} min_y:{minY}");
            return toX + 1;
        }
        private List<HorizontalLineCoordinate> getHorizontalLines(List<_SDB_CONTOUR_> lst_contours) {
            List<HorizontalLineCoordinate> h_lines = new List<HorizontalLineCoordinate>();
            foreach (var contour in lst_contours) {
                if (contour.num_pt < 1) {
                    continue;
                }

                Vector2 currentPoint = new Vector2(contour.pt_s.x, contour.pt_s.y);
                foreach (var section in contour.pt_n) {
                    Vector2 nextPoint = new Vector2(section.pt_e.x, section.pt_e.y);
                    if (Math.Abs(section.amp) < 0.1 && Math.Abs(currentPoint.Y - nextPoint.Y) < 1) {
                        h_lines.Add(new HorizontalLineCoordinate { FromX = (int)currentPoint.X, FromY = (int)currentPoint.Y, ToX = (int)nextPoint.X });
                    }

                    currentPoint = nextPoint;
                }
            }
            return h_lines;
        }
        #endregion
    }
}
